﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic.PowerPacks;

namespace Seagull.Shell.Utils
{
    class MarkerBlinkingManager
    {
        public const int MaxLevel = 2;

        private const int BlinkTimesForSingleFrame = 1;
        private readonly Timer _timer;

        private bool _nextIsDefaultColor;

        public MarkerBlinkingManager(Timer timer)
        {
            _timer = timer;
            _timer.Interval = 500;
            _timer.Tick += OnBlinkTimerTick;
            _timer.Start();
        }

        private readonly object _syncRoot = new object();

        private readonly Dictionary<OvalShape, BlinkInfo> _markers = new Dictionary<OvalShape, BlinkInfo>();

        private static readonly Color _defaultColor = Color.White;

        private static readonly Color[] _colors = new[] { Color.Lime, Color.Yellow, Color.Red };

        public void Blink(OvalShape marker, int level)
        {
            lock(_syncRoot)
            {
                if(!_markers.ContainsKey(marker))
                {
                    _markers[marker] = new BlinkInfo();
                }
                _markers[marker].SetBlinkTime(level, BlinkTimesForSingleFrame);
            }
        }

        private void OnBlinkTimerTick(object sender, EventArgs e)
        {
            lock(_syncRoot)
            {
                foreach(var marker in _markers.Keys.ToArray())
                {
                    var blinkLevel = _markers[marker].Level;
                    if (blinkLevel == -1)
                    {
                        continue;
                    }
                    var nextColor = _nextIsDefaultColor ? _defaultColor : _colors[blinkLevel];
                    marker.FillColor = nextColor;
                    if(nextColor == _defaultColor)
                    {
                        _markers[marker].DecreaseBlinkTime();
                    }
                }
            }
            _nextIsDefaultColor = !_nextIsDefaultColor;
        }

        [DebuggerDisplay("{ToString()}")]
        class BlinkInfo
        {
            private readonly int[] _blinkLevelTimes;

            public int Level
            {
                get
                {
                    for(int level = _blinkLevelTimes.Length - 1; level >= 0; level--)
                    {
                        if(_blinkLevelTimes[level] > 0)
                        {
                            return level;
                        }
                    }
                    return -1;
                }
            }

            public void SetBlinkTime(int level, int blinkTime)
            {
                _blinkLevelTimes[level] = blinkTime;
            }

            public void DecreaseBlinkTime()
            {
                for(int level = 0; level < _blinkLevelTimes.Length; level++)
                {
                    if(_blinkLevelTimes[level] > 0)
                    {
                        --_blinkLevelTimes[level];
                    }
                }
            }

            public BlinkInfo()
            {
                _blinkLevelTimes = new int[MaxLevel + 1];
            }

            public override string ToString()
            {
                var level = Level;
                return string.Format("BlinkLevel: {0}, Times: {1}", level, level >= 0 ? _blinkLevelTimes[level] : 0);
            }
        }
    }
}
